﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using XTools.App_Code;

namespace XTools.App_Code
{
    /// <summary>
    /// 格式转换（16进制、10进制、浮点型、字符串、Bit、Byte数组）
    /// 格式验证、长度验证
    /// 正则表达
    /// 检查是否需要响应
    /// </summary>
    public class FormatHelper
    {
        /// <summary>
        /// 将16进制字符串转化成10进制字符串
        /// </summary>
        public static string hex2dec(string hex)
        {
            return Convert.ToInt32(hex, 16).ToString();
        }

        /// <summary>
        /// 将10进制字符串转化成16进制字符串
        /// </summary>
        public static string dec2hex(int msg)
        {
            string result = Convert.ToString(msg, 16);
            if (result.Length < 2) result = "0"+result;

            return result;
        }

        /// <summary>
        /// 将16进制字符串转化成浮点型字符串
        /// </summary>
        public static string hex2float(string hex)
        {
            uint num = uint.Parse(hex, System.Globalization.NumberStyles.AllowHexSpecifier);
            byte[] bytes = BitConverter.GetBytes(num);
            Array.Reverse(bytes);
            return BitConverter.ToSingle(bytes, 0).ToString();
        }

        /// <summary>
        /// 将浮点型字符串转化成16进制字符串
        /// </summary>
        public static string float2hex(float f)
        {
            byte[] bytes = BitConverter.GetBytes(f);
            return BitConverter.ToString(bytes).Replace("-", "");
        }

        /// <summary>
        /// 将字符串转化成16进制
        /// </summary>
        /// <param name="charset">编码,如"utf-8","gbk"</param>
        /// <param name="flag">字符是否需要逗号分隔</param>
        public static string str2hex(string msg, string charset, bool flag)
        {
            //if ((msg.Length % 2) != 0)
            //{
            //    msg += " ";
            //}
            System.Text.Encoding chs = System.Text.Encoding.GetEncoding(charset);
            byte[] bytes = chs.GetBytes(msg);
            string str = "";
            for (int i = 0; i < bytes.Length; i++)
            {
                str += string.Format("{0:X}", bytes[i]);
                if (flag && (i != bytes.Length - 1))
                {
                    str += string.Format("{0}", ",");
                }
            }
            return str.ToLower();
        }

        /// <summary>
        /// 将16进制转换成字符串
        /// </summary>
        /// <param name="charset">编码,如"utf-8","gbk"</param>
        public static string hex2str(string hex, string charset)
        {
            //换行符 十六进制da替换成0a
            string tempHex = string.Empty;
            for (int i = 0; i < hex.Length / 2; i++)
            {
                string str = hex.Substring(i * 2, 2).ToLower();
                if (str == "da")
                {
                    str = "0A";
                }
                tempHex += str;
            }
            hex = tempHex;
           
            //注释后，解决了链接类型数据，行末尾有空格导致被截断问题
            //while (hex.LastIndexOf("00") != -1)
            //{
            //    hex = hex.Substring(0, hex.LastIndexOf("00"));
            //}
            if (hex == null)
                throw new ArgumentNullException("hex");
            hex = hex.Replace(",", "");
            hex = hex.Replace("/n", "");
            hex = hex.Replace("//", "");
            hex = hex.Replace(" ", "");
            if (hex.Length % 2 != 0)
            {
                hex += "20";
            }
            byte[] bytes = new byte[hex.Length / 2];
            for (int i = 0; i < bytes.Length; i++)
            {
                try
                {
                    bytes[i] = byte.Parse(hex.Substring(i * 2, 2),
                    System.Globalization.NumberStyles.HexNumber);
                }
                catch
                {
                    throw new ArgumentException("hex is not a valid hex number!", "hex");
                }
            }
            System.Text.Encoding chs = System.Text.Encoding.GetEncoding(charset);
            return chs.GetString(bytes).Replace("\n", "\r\n").Replace("\0", "");
        }

        /// <summary>
        /// 将2进制字符串转化成16进制字符串
        /// </summary>
        public static string bit2hex(string msg)
        {
            return Convert.ToString(Convert.ToInt32(msg, 2), 16);//2-->10-->16
        }

        /// <summary>
        /// 将16进制字符串转化成2进制字符串
        /// </summary>
        public static string hex2bit(string hex)
        {
            return Convert.ToString(Convert.ToInt32(hex, 16), 2);//16-->10-->2
        }

        /// <summary>
        /// 将字节数据转换成16进制字符串
        /// </summary>
        public static string ByteToString(byte[] arrByte)
        {
            string returnStr = "";
            if (arrByte != null && arrByte.Length > 0)
            {
                for (int i = 0; i < arrByte.Length; i++)
                {
                    returnStr += arrByte[i].ToString("X2") + " ";
                }
            }
            return returnStr;
        }
        public static string ByteToStringEx(byte[] arrByte)
        {
            string returnStr = "";
            if (arrByte != null && arrByte.Length > 0)
            {
                for (int i = 0; i < arrByte.Length; i++)
                {
                    string tempStr =  arrByte[i].ToString("X2");
                    if (tempStr.Length < 2) tempStr = "0" + tempStr;
                    returnStr += tempStr;
                }
            }
            return returnStr;
        }

        /// <summary>
        /// 将字符串转16进制字节数组
        /// </summary>
        public static byte[] StringToByte(string strHex)
        {
            if ((strHex.Length % 2) != 0)
            {
                strHex = string.Format("0{0}", strHex);
            }
            byte[] returnByte = new byte[strHex.Length / 2];
            for (int i = 0; i < strHex.Length; i += 2)
            {
                returnByte[i / 2] = Convert.ToByte(strHex.Substring(i, 2), 16);
            }
            return returnByte;
        }

        /// <summary>
        /// 将stations.ini中内容按照类型转化成Str
        /// </summary>
        public static string ToStr(string hex, string type)
        {
            if (hex == "")
            {
                return hex;
            }
            if (hex.Length == 1) hex = "0" + hex;
          
            int t = FormatHelper.FieldType(type);
            string msg = "";
            string tempHex = "";
            switch (t)
            {
                case 0://字符串
                    msg = FormatHelper.hex2str(hex, "gbk");
                    break;
                case 1://十进制
                    for (int i = 0; i < hex.Length / 2; i++)
                    {
                        tempHex = hex.Substring(i * 2, 2) + tempHex;
                    }
                    hex = tempHex;
                    msg = FormatHelper.hex2dec(hex);
                    break;
                case 2://十六进制
                    for (int i = 0; i < hex.Length / 2; i++)
                    {
                        tempHex = hex.Substring(i * 2, 2) + tempHex;
                    }
                    hex = tempHex;
                    msg = hex.ToUpper();
                    break;
                case 3://浮点型
                    msg = FormatHelper.hex2float(hex);
                    break;
                case 4://bit
                    msg = FormatHelper.hex2bit(hex).PadLeft(8, '0');
                    break;
                case 5://链接
                    msg = FormatHelper.hex2str(hex, "gbk");
                    break;
            }
            return msg.Trim();
        }

        /// <summary>
        /// 将界面中的内容按照类型转化成Hex
        /// </summary>
        public static string ToHex(string msg, string type, string length)
        {
            int t = FormatHelper.FieldType(type);
            int l = Convert.ToInt32(length) * 2;
            string hex = "";
            string tempHex = "";
            switch (t)
            {
                case 0://字符串
                    hex = FormatHelper.str2hex(msg, "gbk", false);
                    //如果长度大于限制长度，截取
                    if (hex.Length > l)
                    {
                        hex = hex.Substring(0, l);
                    }
                    //如果长度小于限制长度，后面补0
                    else if (hex.Length < l)
                    {
                        int counts = l - hex.Length;
                        for (int i = 0; i < counts; i++)
                        {
                            hex += "0";
                        }
                    }
                    break;
                case 1://十进制
                    if (msg.Trim() != "")
                        hex = FormatHelper.dec2hex(Convert.ToInt32(msg));
                    //如果十六进制只有一位，前面补0
                    if (hex.Length % 2 == 1)
                    {
                        hex = "0" + hex;
                    }
                    //如果长度小于限制长度，前面补0
                    if (hex.Length < l)
                    {
                        int counts = l - hex.Length;
                        for (int i = 0; i < counts; i++)
                        {
                            hex = "0" + hex;
                        }
                    }

                    for (int i = 0; i < hex.Length / 2; i++)
                    {
                        tempHex = hex.Substring(i * 2, 2) + tempHex;
                    }
                    hex = tempHex;

                    break;
                case 2://十六进制
                    hex = msg;
                    //如果长度小于限制长度，前面补0
                    if (hex.Length < l)
                    {
                        int counts = l - hex.Length;
                        for (int i = 0; i < counts; i++)
                        {
                            hex = "0" + hex;
                        }
                    }

                    for (int i = 0; i < hex.Length / 2; i++)
                    {
                        tempHex = hex.Substring(i * 2, 2) + tempHex;
                    }
                    hex = tempHex;

                    break;
                case 3://浮点型，转换之后十六进制为4个Byte
                    if (msg.Trim() != "")
                    {
                        hex = FormatHelper.float2hex(Convert.ToSingle(msg));
                    }
                    else
                    {
                        hex = "00000000";
                    }
                    break;
                case 4://bit
                    //如果长度小于限制长度，前面补0
                    if (msg.Length < l * 4)
                    {
                        int counts = l * 4 - msg.Length;
                        for (int i = 0; i < counts; i++)
                        {
                            msg = "0" + msg;
                        }
                    }
                    hex = FormatHelper.bit2hex(msg);
                    //如果长度小于限制长度，前面补0
                    if (hex.Length < l)
                    {
                        int counts = l - hex.Length;
                        for (int i = 0; i < counts; i++)
                        {
                            hex = "0" + hex;
                        }
                    }
                    break;
                case 5://链接
                    hex = FormatHelper.str2hex(msg, "gbk", false);
                    hex = hex.Replace("da", "0a");
                    hex = hex.Replace("DA", "0A");

                    //获取该字段所需域长度
                    if (hex.Length % (64 * 2) != 0)
                    {
                        l = (hex.Length / (64 * 2) + 1) * 64 * 2;

                        //如果长度小于限制长度，后面补0
                        if (hex.Length < l)
                        {
                            int counts = l - hex.Length;
                            for (int i = 0; i < counts; i++)
                            {
                                hex += "0";
                            }
                        }
                    }
                    else if (hex.Length == 0)
                    {
                        for (int i = 0; i < 64; i++)
                        {
                            hex += "00";
                        }
                    }
                    else if (hex.Length % (64 * 2) == 0)
                    {
                        string last_str = hex.Substring(hex.Length - 2, 2);
                        if (last_str == "20")
                        {
                            hex = hex.Substring(0, hex.Length - 2) + "00";
                        }
                        else if (last_str != "00")
                        {
                            for (int i = 0; i < 64; i++)
                            {
                                hex += "00";
                            }
                        }
                    }

                    break;
            }
            return hex;
        }

        /// <summary>
        /// 将界面中的内容按照类型转化成Hex
        /// </summary>
        public static string FmtHex(string msg, string length)
        {
            int l = Convert.ToInt32(length) * 2;
            string hex = "";
            hex = msg;
            //如果长度小于限制长度，前面补0
            if (hex.Length < l)
            {
                int counts = l - hex.Length;
                for (int i = 0; i < counts; i++)
                {
                    hex = "0" + hex;
                }
            }
            return hex;
        }

        /// <summary>
        /// 格式验证、长度验证
        /// </summary>
        /// <param name="msg">需验证对象</param>
        /// <param name="str">长度和类型</param>
        /// <returns>验证结果</returns>
        public static string Verification(string msg, string str)
        {
            if (msg == "") return "true";
            string[] s = str.Split('|');
            int t = FormatHelper.FieldType(s[0]);
            if (s[1].IndexOf(".") != -1)
            {
                s[1] = s[1].Substring(1);
            }
            int l = Convert.ToInt32(s[1]);
            string result = "true";
            switch (t)
            {
                case 0://字符串
                    int count = System.Text.Encoding.Default.GetByteCount(msg);
                    if (count > l)
                    {
                        result = "超出长度，请重新输入";//超出长度
                    }
                    break;
                case 1://十进制
                    if (!QuickValidate("^[0-9]\\d*$", msg))
                    {
                        result = "格式有误，只能输入数字";//只能输入（0-9）
                    }
                    else
                    {
                        if (l <= 4)//防止十六进制转十进制时，超出32位整数长度，导致错误，最大“FFFFFFFF”
                        {
                            string hex = "";
                            for (int i = 0; i < l * 2; i++)
                            {
                                hex += "F";
                            }
                            int dec = Convert.ToInt32(FormatHelper.hex2dec(hex));
                            if (Convert.ToInt32(msg) > dec && dec != -1)
                            {
                                result = "格式有误，最大只能输入" + dec;//超出最大值
                            }
                        }
                    }
                    break;
                case 2://十六进制
                    l = l * 2;
                    if (msg.Length > l)
                    {
                        result = "超出长度，请重新输入";//超出长度
                    }
                    else if (!QuickValidate("^[0-9a-fA-F]+$", msg))
                    {
                        result = "格式有误，只能输入（0-9，A-F）";//只能输入（0-9，A-F）
                    }
                    break;
                case 3://浮点型
                    if (!QuickValidate("^[-+\\d]?\\d+(.\\d+)?$", msg))
                    {
                        result = "格式有误，只能输入数字和小数点";//只能输入数字和小数点
                    }
                    break;
                case 4://bit
                    if (msg.Length > l)
                    {
                        result = "超出长度，请重新输入";//超出长度
                    }
                    else if (!QuickValidate("^[0-1]*$", msg))
                    {
                        result = "格式有误、只能输入（0、1），请重新输入";//只能输入（0、1）
                    }
                    break;
            }
            return result;
        }

        /// <summary>
        /// 正则验证
        /// </summary>
        public static bool QuickValidate(string _express, string _value)
        {
            if (_value == null || _value.Length == 0)
            {
                return false;
            }
            return new Regex(_express).IsMatch(_value);
        }

        /// <summary>
        /// 字段类型
        /// </summary>
        public static int FieldType(string str)
        {
            if (str == "字符串")
            {
                return 0;
            }
            else if (str == "十进制")
            {
                return 1;
            }
            else if (str == "十六进制")
            {
                return 2;
            }
            else if (str == "浮点型")
            {
                return 3;
            }
            else if (str == "bit")
            {
                return 4;
            }
            else if (str == "链接")
            {
                return 5;
            }
            return 0;
        }

        /// <summary>
        /// 字段类型
        /// </summary>
        public static string FieldTypeFormat(string str)
        {
            if (str == "字符串")
            {
                return "%s";
            }
            else if (str == "十进制")
            {
                return "%d";
            }
            else if (str == "十六进制")
            {
                return "%x";
            }
            else if (str == "浮点型")
            {
                return "%f";
            }
            else if (str == "bit")
            {
                return "%b";
            }
            else if (str == "链接")
            {
                return "%l";
            }
            return "";
        }

        /// <summary>
        /// 各种类型数据转换成byte数组
        /// </summary>
        /// <param name="msg">需处理对象</param>
        /// <param name="des">byte数组</param>
        /// <param name="index">位置</param>
        /// <param name="length">长度</param>
        /// <param name="type">类型</param>
        public static void ToBytes(string msg, ref byte[] des, ref int index, int length, string type)
        {
            int t = FormatHelper.FieldType(type);
            int number = 0;
            switch (t)
            {
                case 0://字符串
                    msg = str2hex(msg, "gbk", false);
                    byte[] strArr = StringToByte(msg);

                    for (int j = 0; j < length; j++)
                    {
                        if (j >= strArr.Length)
                        {
                            des[index] = 0;
                        }
                        else
                        {
                            des[index] = strArr[j];
                        }
                        index++;
                    }
                    return;
                case 1://十进制
                    if (msg.Trim() != "")
                    {
                        number = Convert.ToInt32(msg);
                    }
                    break;
                case 2://十六进制
                    if (msg.Trim() != "")
                    {
                        msg = msg.Replace("&H", "0x").Trim();
                        number = Convert.ToInt32(msg, 16);
                    }
                    break;
                case 3://浮点型
                    if (msg.Trim() != "")
                    {
                        msg = FormatHelper.float2hex(Convert.ToSingle(msg));
                    }
                    else
                    {
                        msg = "00000000";
                    }

                    byte[] floatArr = StringToByte(msg);

                    for (int j = 0; j < 4; j++)
                    {
                        des[index] = floatArr[j];
                        index++;
                    }
                    return;
                case 4://bit
                    number = Convert.ToInt32(msg, 2);
                    break;
                case 5://链接
                    if (msg.Length == 0) return;

                    msg = str2hex(msg, "gbk", false);

                    if (msg.Length % (64 * 2) == 0)
                    {
                        string last_str = msg.Substring(msg.Length - 2, 2);
                        if (last_str == "20")
                        {
                            msg = msg.Substring(0, msg.Length - 2) + "00";
                        }
                        else if (last_str != "00")
                        {
                            for (int i = 0; i < 64; i++)
                            {
                                msg += "00";
                            }
                        }
                    }

                    byte[] linkArr = StringToByte(msg);

                    int l = 0;
                    //获取该字段所需域长度
                    if (linkArr.Length % (64 * 2) != 0)
                    {
                        l = (linkArr.Length / 64 + 1) * 64;
                    }
                    else
                    {
                        l = linkArr.Length;
                    }

                    for (int j = 0; j < l; j++)
                    {
                        if (j >= linkArr.Length)
                        {
                            des[index] = 0;
                        }
                        else
                        {
                            des[index] = linkArr[j];
                        }
                        index++;
                    }
                    return;
            }
            byte[] numberBytes = BitConverter.GetBytes(number);
            for (int i = 0; i < length; i++)
            {
                if (i < numberBytes.Length)
                {
                    des[index] = numberBytes[i];
                }
                else
                {
                    des[index] = 0;
                }
                index++;
            }
        }

        /// <summary>
        /// 检查是否需要响应
        /// </summary>
        public static bool TestBit(int b0, byte n)
        {
            bool result = false;

            if (n > 0)
            {
                for (int i = 1; i <= n; i++)
                {
                    b0 = b0 / 2;
                }
            }

            if (b0 % 2 == 1)
            {
                result = true;
            }

            return result;
        }

        /// <summary>
        /// 转换为二进制
        /// </summary>
        public static byte SetBit(byte b0, byte n)
        {
            byte bbb;
            byte[] c = new byte[8];
            c[0] = 1;
            c[1] = 2;
            c[2] = 4;
            c[3] = 8;
            c[4] = 16;
            c[5] = 32;
            c[6] = 64;
            c[7] = 128;
            if (!TestBit(b0, n))
            {
                bbb = Convert.ToByte(b0 + c[n]);
            }
            else
            {
                bbb = b0;
            }

            return bbb;
        }

        //10进制转二进制
        public static string DecimalToBinary(int nData, int Num)
        {
            string strData = Convert.ToString(nData, 2);
            if (strData.Length < Num)
            {
                int leng = strData.Length;
                for (int i = 0; i < Num - leng; i++)
                {
                    strData = "0" + strData;
                }
            }
            strData = strData.Substring(strData.Length - Num,Num);
            return strData;
        }
        //16进制转2进制
        public static string HexToBinary(string str, int num)
        {
            return DecimalToBinary(HexToDecimal(str), num);
        }
        //16进制转10进制
        private static int HexToDecimal(string str)
        {
            int nData = Convert.ToInt32(str, 16);
            return nData;
        }
    }
}